#include <iostream>
#include <fstream>
#include <vector>

namespace MultipleHNSW {
    template<typename T>
    T *load_vecs(const char *filename, int &n_data, int &dim) {
        std::ifstream in(filename, std::ios::binary);
        if (!in.is_open()) {
            std::cerr << "Open file error" << std::endl;
            exit(-1);
        }

        in.read((char *) &dim, 4);

        in.seekg(0, std::ios::end);
        std::ios::pos_type ss = in.tellg();
        size_t fsize = (size_t) ss;
        n_data = (int) (fsize / (dim + 1) / 4);

        T *data = new T[(size_t) n_data * (size_t) dim];

        in.seekg(0, std::ios::beg);
        for (int i = 0; i < n_data; i++) {
            in.seekg(4, std::ios::cur);
            in.read((char *) (data + i * dim), dim * sizeof(T));
        }
        in.close();

        return data;
    }

    std::vector<float *>
    read_data(const char *dataset_name, int &n_query, int &top_k, int &n_base, int &data_dim) {
        char path[256];
        std::printf("load ground truth\n");
        std::sprintf(path, "../data/%s/gnd-%d.ivecs", dataset_name, top_k);
        int *gnd = load_vecs<int>(path, n_query, top_k);
//    std::printf("%d %d %d %d %d %d\n", gnd[0], gnd[1], gnd[2], gnd[3], gnd[4], gnd[10]);

        std::printf("load query\n");
        sprintf(path, "../data/%s/query.fvecs", dataset_name);
        float *query = load_vecs<float>(path, n_query, data_dim);
//    std::printf("%d %d %d %d %d\n", query[0], query[1], query[2], query[3], query[4]);

        std::printf("load base\n");
        sprintf(path, "../data/%s/base.fvecs", dataset_name);
        float *base = load_vecs<float>(path, n_base, data_dim);
//    std::printf("%d %d %d %d %d\n", base[0], base[1], base[2], base[3], base[4]);
        std::vector<float *> res(3);
        res[0] = base;
        res[1] = query;
        res[2] = (float *) gnd;
        return res;
    }

}
